/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tpgen.manchester.oppl;

import java.util.ArrayList;
import java.util.List;
import tpgen.grammar.Alt;
import tpgen.grammar.Grammar;
import tpgen.grammar.NonTerminal;
import tpgen.grammar.RandomVariable;
import tpgen.grammar.Repeat;
import tpgen.grammar.Sequence;
import tpgen.grammar.Symbol;
import tpgen.grammar.Terminal;

/**
 *
 * @author shanki
 */
@Deprecated
public class ManchesterSyntaxGrammar extends Grammar {

    private NonTerminal axiom;
    private List<Symbol> variableTypes = new ArrayList<Symbol>();
    
    public ManchesterSyntaxGrammar(ManchesterPropability prop) {        
        
        Alt dataType    = new Alt();
        dataType.add(new Terminal("integer"), 1);
        dataType.add(new Terminal("decimal"), 1);
        dataType.add(new Terminal("float"), 1);
        dataType.add(new Terminal("string"), 1);        
 
        Terminal comma      = new Terminal(",");
        Terminal some       = new Terminal("some");
        Terminal only       = new Terminal("only");
        Terminal value      = new Terminal("value");
        Terminal min        = new Terminal("min");
        Terminal exactly    = new Terminal("exactly");
        Terminal max        = new Terminal("max");
        Terminal lpar       = new Terminal("(");
        Terminal rpar       = new Terminal(")");
        Terminal or         = new Terminal("or");
        Terminal and        = new Terminal("and");
        Terminal not        = new Terminal("not");
        
        Terminal classFrame             = new Terminal("Class:");
        Terminal objectPropertyFrame    = new Terminal("ObjectProperty:");
        Terminal dataPropertyFrame      = new Terminal("DataProperty:");
        Terminal individualFrame        = new Terminal("Individual:");        
        Terminal characteristics        = new Terminal("Characteristics:");
        Terminal subClassOf             = new Terminal("SubClassOf:");
        Terminal equivalentTo           = new Terminal("EquivalentTo:");
        Terminal disjointWith           = new Terminal("DisjointWith:");
        Terminal subPropertyOf          = new Terminal("SubPropertyOf:");
        Terminal inverseOf              = new Terminal("InverseOf:");
        Terminal range                  = new Terminal("Range:");
        Terminal domain                 = new Terminal("Domain:");
        Terminal instanceOf             = new Terminal("InstanceOf:");
        Terminal types                  = new Terminal("Types:");
        Terminal facts                  = new Terminal("Facts:");
        Terminal sameAs                 = new Terminal("SameAs:");
        Terminal differentFrom          = new Terminal("DifferentFrom:");
        
        Terminal functional             = new Terminal("Functional");
        Terminal symmetric              = new Terminal("Symmetric");
        Terminal reflexive              = new Terminal("Reflexive");
        Terminal transitive             = new Terminal("Transitive");
        Terminal antiSymmetric          = new Terminal("AntiSymmetric");
        Terminal irreflexive            = new Terminal("Irreflexive");
        Terminal inverseFunctional      = new Terminal("InverseFunctional");
                       
        NonTerminal classDescription    = new NonTerminal("ClassDescription");
        
        RandomVariable primitiveClass   = new RandomVariable("Class");
        variableTypes.add(primitiveClass);
        RandomVariable objectProperty   = new RandomVariable("ObjectProperty");
        variableTypes.add(objectProperty);
        RandomVariable dataProperty     = new RandomVariable("DataProperty");
        variableTypes.add(dataProperty);
        RandomVariable individual       = new RandomVariable("Individual");
        variableTypes.add(individual);
        RandomVariable constant         = new RandomVariable("Constant");
        variableTypes.add(constant);
        RandomVariable number     = new RandomVariable("Literal");
        variableTypes.add(number);
        
        Repeat individualPlus               = new Repeat(individual, false, 0.5);
        Repeat dataPropertyPlus             = new Repeat(dataProperty, false, 0.5);
        Repeat objectPropertyPlus           = new Repeat(objectProperty, false, 0.5);
        
        Alt objectRestrictionAlt            = new Alt();
        objectRestrictionAlt.add(new Sequence(objectProperty, some, classDescription), prop.get(Construct.objectRestriction_some));
        objectRestrictionAlt.add(new Sequence(objectProperty, only, classDescription), prop.get(Construct.objectRestriction_only));
        objectRestrictionAlt.add(new Sequence(objectProperty, value, individual), prop.get(Construct.objectRestriction_value));
        objectRestrictionAlt.add(new Sequence(objectProperty, min, number), prop.get(Construct.objectRestriction_min));
        objectRestrictionAlt.add(new Sequence(objectProperty, exactly, number), prop.get(Construct.objectRestriction_exactly));
        objectRestrictionAlt.add(new Sequence(objectProperty, max, number), prop.get(Construct.objectRestriction_max));
        
        NonTerminal objectRestriction       = new NonTerminal("ObjectRestriction", objectRestrictionAlt);

        
        Alt dataRestrictionAlt              = new Alt();
        // v gramatike je namiesto dataType dataRange, rozhodli sme sa to zjednodusit
        dataRestrictionAlt.add(new Sequence(dataProperty, some, dataType), prop.get(Construct.dataRestriction_some));
        // v gramatike je namiesto dataType dataRange, rozhodli sme sa to zjednodusit
        dataRestrictionAlt.add(new Sequence(dataProperty, only, dataType), prop.get(Construct.dataRestriction_only));
        dataRestrictionAlt.add(new Sequence(dataProperty, min, number), prop.get(Construct.dataRestriction_min));
        dataRestrictionAlt.add(new Sequence(dataProperty, exactly, number), prop.get(Construct.dataRestriction_exactly));
        dataRestrictionAlt.add(new Sequence(dataProperty, max, number), prop.get(Construct.dataRestriction_max));
        
        NonTerminal dataRestriction         = new NonTerminal("DataRestriction", dataRestrictionAlt);
        
        Sequence individualList             = new Sequence(individual, new Repeat(new Sequence(comma, individual), true, 0.5));
        
        Alt nonnaryDescriptionAlt           = new Alt();
        nonnaryDescriptionAlt.add(primitiveClass, 1);
        nonnaryDescriptionAlt.add(objectRestriction, 1);
        nonnaryDescriptionAlt.add(dataRestriction, 1);
        nonnaryDescriptionAlt.add(new Sequence(not, classDescription), prop.get(Construct.classNot));
        nonnaryDescriptionAlt.add(new Sequence(new Terminal("oneOf {"), individualList, new Terminal("}")), prop.get(Construct.oneOf));
        
        NonTerminal nonnaryDescription      = new NonTerminal("NonNaryDescription", nonnaryDescriptionAlt);
        NonTerminal classUnion              = new NonTerminal("ClassUnion", new Sequence(nonnaryDescription, new Repeat(new Sequence(or, nonnaryDescription), true, prop.get(Construct.classUnion))));
        NonTerminal classIntersection       = new NonTerminal("ClassIntersection", new Sequence(classUnion, new Repeat(new Sequence(and, classUnion), true, prop.get(Construct.classIntersection))));
        classDescription.setSymbol(classIntersection);
        
        Repeat repClassDescription          = new Repeat(classDescription, false, 0.5);
        
        NonTerminal subClassAxiom           = new NonTerminal("SubClassAxiom", new Sequence(classFrame, classDescription, subClassOf, classDescription));
        NonTerminal equivalentClassAxiom    = new NonTerminal("EquivalentClassAxiom", new Sequence(classFrame, classDescription, equivalentTo, repClassDescription));
        NonTerminal disjointClassAxiom      = new NonTerminal("DisjointClassAxiom", new Sequence(classFrame, classDescription, disjointWith, repClassDescription));
        NonTerminal functionalObjectPropertyAxiom   = new NonTerminal("FunctionalObjectPropertyAxiom", new Sequence(objectPropertyFrame, objectProperty, characteristics, functional));
        
        NonTerminal symmetricObjectPropertyAxiom    = new NonTerminal("SymmetricObjectPropertyAxiom", new Sequence(objectPropertyFrame, objectProperty, characteristics, symmetric));
        NonTerminal reflexiveObjectPropertyAxiom    = new NonTerminal("ReflexiveObjectPropertyAxiom", new Sequence(objectPropertyFrame, objectProperty, characteristics, reflexive));
        NonTerminal transitiveObjectPropertyAxiom   = new NonTerminal("TransitiveObjectPropertyAxiom", new Sequence(objectPropertyFrame, objectProperty, characteristics, transitive));
        NonTerminal antiSymmetricObjectPropertyAxiom    = new NonTerminal("AntisymmetricObjectPropertyAxiom", new Sequence(objectPropertyFrame, objectProperty, characteristics, antiSymmetric));
        NonTerminal irreflexiveObjectPropertyAxiom      = new NonTerminal("IrreflexiveObjectPropertyAxiom", new Sequence(objectPropertyFrame, objectProperty, characteristics, irreflexive));
        
        NonTerminal subObjectPropertyAxiom  = new NonTerminal("SubObjectPropertyAxiom", new Sequence(objectPropertyFrame, objectProperty, subPropertyOf, objectProperty));
        NonTerminal equivalentObjectPropertyAxiom   = new NonTerminal("EquivalentObjectPropertyAxiom", new Sequence(objectPropertyFrame, objectProperty, equivalentTo, objectPropertyPlus));
        NonTerminal disjointObjectPropertyAxiom     = new NonTerminal("DisjointObjectPropertyAxiom", new Sequence(objectPropertyFrame, objectProperty, disjointWith, objectPropertyPlus));
        NonTerminal inversePropertyAxiom            = new NonTerminal("InversePropertyAxiom", new Sequence(objectPropertyFrame, objectProperty, inverseOf, objectProperty));
        NonTerminal inverseFunctionalPropertyAxiom  = new NonTerminal("InverseFunctionalPropertyAxiom", new Sequence(objectPropertyFrame, objectProperty, characteristics, inverseFunctional));
        NonTerminal functionalDataPropertyAxiom    = new NonTerminal("FunctionalDataPropertyAxiom", new Sequence(dataPropertyFrame, dataProperty, characteristics, functional));
        NonTerminal objectPropertyRangeAxiom        = new NonTerminal("ObjectPropertyRangeAxiom", new Sequence(objectPropertyFrame, objectProperty, range, classDescription));
        NonTerminal objectPropertyDomainAxiom       = new NonTerminal("ObjectPropertyDomainAxiom", new Sequence(objectPropertyFrame, objectProperty, domain, classDescription));
        NonTerminal subDataPropertyAxiom        = new NonTerminal("SubDataPropertyAxiom", new Sequence(dataPropertyFrame, dataProperty, subPropertyOf, dataProperty));
        NonTerminal equivalentDataPropertyAxiom     = new NonTerminal("EquivalentDataPropertyAxiom", new Sequence(dataPropertyFrame, dataProperty, equivalentTo, dataPropertyPlus));
        
        // in documentation there was an error: both DisjointDataPropertyAxiom and DisjointObjectPropertyAxiom were called DisjointPropertyAxiom
        NonTerminal disjointDataPropertyAxiom       = new NonTerminal("DisjointDataPropertyAxiom", new Sequence(dataPropertyFrame, dataProperty, disjointWith, dataPropertyPlus));
        NonTerminal dataPropertyDomainAxiom         = new NonTerminal("DataPropertyDomainAxiom", new Sequence(dataPropertyFrame, dataProperty, domain, classDescription));
        // v gramatike je namiesto dataType dataRange, rozhodli sme sa to zjednodusit
        NonTerminal dataPropertyRangeAxiom          = new NonTerminal("DataPropertyRangeAxiom", new Sequence(dataPropertyFrame, dataProperty, range, dataType));
        
        Alt classAssertionAxiomAlt                  = new Alt();
        classAssertionAxiomAlt.add(new Sequence(individualFrame, individual, instanceOf), prop.get(Construct.classAssertionAxiom_individual));
        classAssertionAxiomAlt.add(new Sequence(individualFrame, types, classDescription), prop.get(Construct.classAssertionAxiom_types));
        
        
        
        NonTerminal classAssertionAxiom             = new NonTerminal("ClassAssertionAxiom", classAssertionAxiomAlt);
        
        NonTerminal objectPropertyAssertionAxiom    = new NonTerminal("ObjectPropertyAssertionAxiom", new Sequence(individualFrame, individual, facts, objectProperty, individual));
        NonTerminal dataPropertyAssertionAxiom      = new NonTerminal("DataPropertyAssertionAxiom", new Sequence(individualFrame, individual, facts, dataProperty, constant));
        NonTerminal negativeObjectPropertyAssertionAxiom    = new NonTerminal("NegativeObjectPropertyAssertion", new Sequence(individualFrame, individual, facts, not, objectProperty, individual));
        NonTerminal negativeDataPropertyAssertionAxiom      = new NonTerminal("NegativeDataPropertyAssertionAxiom", new Sequence(individualFrame, individual, facts, not, dataProperty, constant));
        NonTerminal sameAsAxiom     = new NonTerminal("SameAsAxiom", new Sequence(individualFrame, individual, sameAs, individualPlus));
        NonTerminal differentFromAxiom  = new NonTerminal("DifferentFromAxiom", new Sequence(individualFrame, individual, differentFrom, individualPlus));
        
        // I think we do not need this axiom
        //NonTerminal entityAnnotationAxiom   = new NonTerminal("EntityAnnotationAxiom", new Sequence(iri, annotationProperty, constant));
     
        Alt axiomAlt        = new Alt();
        axiomAlt.add(subClassAxiom, prop.get(Construct.subClassAxiom));
//        axiomAlt.add(equivalentClassAxiom, prop.get(Construct.equivalentClassAxiom));
//        axiomAlt.add(disjointClassAxiom, prop.get(Construct.disjointClassAxiom));
        axiomAlt.add(functionalObjectPropertyAxiom, prop.get(Construct.functionalObjectPropertyAxiom));
        axiomAlt.add(symmetricObjectPropertyAxiom, prop.get(Construct.symmetricObjectPropertyAxiom));
        axiomAlt.add(reflexiveObjectPropertyAxiom, prop.get(Construct.reflexiveObjectPropertyAxiom));
        axiomAlt.add(transitiveObjectPropertyAxiom, prop.get(Construct.transitiveObjectPropertyAxiom));
        axiomAlt.add(antiSymmetricObjectPropertyAxiom, prop.get(Construct.antiSymmetricObjectPropertyAxiom));
        axiomAlt.add(irreflexiveObjectPropertyAxiom, prop.get(Construct.irreflexiveObjectPropertyAxiom));
        axiomAlt.add(subObjectPropertyAxiom, prop.get(Construct.subObjectPropertyAxiom));
//        axiomAlt.add(equivalentObjectPropertyAxiom, prop.get(Construct.equivalentObjectPropertyAxiom));
//        axiomAlt.add(disjointObjectPropertyAxiom, prop.get(Construct.disjointObjectPropertyAxiom));
        axiomAlt.add(inversePropertyAxiom, prop.get(Construct.inversePropertyAxiom));
        axiomAlt.add(inverseFunctionalPropertyAxiom, prop.get(Construct.inverseFunctionalPropertyAxiom));
        axiomAlt.add(functionalDataPropertyAxiom, prop.get(Construct.functionalDataPropertyAxiom));
        axiomAlt.add(objectPropertyRangeAxiom, prop.get(Construct.objectPropertyRangeAxiom));
        axiomAlt.add(objectPropertyDomainAxiom, prop.get(Construct.objectPropertyDomainAxiom));
        axiomAlt.add(subDataPropertyAxiom, prop.get(Construct.subDataPropertyAxiom));
//        axiomAlt.add(equivalentDataPropertyAxiom, prop.get(Construct.equivalentDataPropertyAxiom));
//        axiomAlt.add(disjointDataPropertyAxiom, prop.get(Construct.disjointDataPropertyAxiom));
        axiomAlt.add(dataPropertyDomainAxiom, prop.get(Construct.dataPropertyDomainAxiom));
        axiomAlt.add(dataPropertyRangeAxiom, prop.get(Construct.dataPropertyRangeAxiom));
        axiomAlt.add(classAssertionAxiom, prop.get(Construct.classAssertionAxiom));
        axiomAlt.add(objectPropertyAssertionAxiom, prop.get(Construct.objectPropertyAssertionAxiom));
        axiomAlt.add(dataPropertyAssertionAxiom, prop.get(Construct.dataPropertyAssertionAxiom));
        axiomAlt.add(negativeObjectPropertyAssertionAxiom, prop.get(Construct.negativeObjectPropertyAssertionAxiom));
        axiomAlt.add(negativeDataPropertyAssertionAxiom, prop.get(Construct.negativeDataPropertyAssertionAxiom));
//        axiomAlt.add(sameAsAxiom, prop.get(Construct.sameAsAxiom));
//        axiomAlt.add(differentFromAxiom, prop.get(Construct.differentFromAxiom));
        
        axiom   = new NonTerminal("Axiom", axiomAlt);
        
        dataType.setOnetoUniformPropability();
        objectRestrictionAlt.setOnetoUniformPropability();
        dataRestrictionAlt.setOnetoUniformPropability();
        nonnaryDescriptionAlt.setOnetoUniformPropability();
        classAssertionAxiomAlt.setOnetoUniformPropability();
        axiomAlt.setOnetoUniformPropability();
    }

    @Override
    public Symbol getStartSymbol() {
        return axiom;
    }

    @Override
    public List<Symbol> getVariableTypes() {
        return variableTypes;
    }

}